package com.atguigu.java8.stream;

import com.atguigu.java8.lambda.Employee;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

public class TestStreamAPI2 {

    List<Employee> employees = Arrays.asList(
            new Employee("张三", 18, 9999.99, Employee.Status.FREE),
            new Employee("李四", 38, 5555.99, Employee.Status.BUSY),
            new Employee("王五", 50, 6666.66, Employee.Status.VOCATION),
            new Employee("赵六", 16, 3333.33, Employee.Status.FREE),
            new Employee("田七", 8, 7777.77, Employee.Status.BUSY)
    );

    // 内部迭代：迭代操作由Stream API完成
    @Test
    public void test1() {
        // filter：接收lambda，从流中排除某些元素
        // 中间操作：不会执行任何操作
        Stream<Employee> employeeStream = employees.stream().filter(e -> {
            System.out.println("流的中间操作filter");
            return e.getAge() >= 35;
        });

        // 终止操作：一次性执行全部内容，即”惰性求值“
        employeeStream.forEach(System.out::println);
    }

    // 外部迭代：
    @Test
    public void test2() {
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

    @Test
    public void test3() {
        // limit：截断流，使其元素不超过给定数量
        employees.stream().filter(e -> {
            System.out.println("短路");
            return e.getSalary() > 6000;
        }).limit(2).forEach(System.out::println);
    }

    @Test
    public void test4() {
        // skip(n)：跳过元素，返回一个扔掉了前n个元素的流。若流中元素不足n个，则返回一个空流。与limit(n)互补
        employees.stream().filter(e -> e.getSalary() > 5000).skip(2).forEach(System.out::println);
    }

    @Test
    public void test5() {
        // distinct：筛选，通过流所生成元素的hashCode()和equals()去除重复元素
        List<Employee> list = new ArrayList<>(employees);
        list.add(new Employee("田七", 8, 7777.77, Employee.Status.BUSY));
        list.add(new Employee("田七", 8, 7777.77, Employee.Status.BUSY));
        list.add(new Employee("田七", 8, 7777.77, Employee.Status.BUSY));
        list.stream().filter(e -> e.getSalary() > 5000)
                .distinct()
                .forEach(System.out::println);
    }

    @Test
    public void test6() {
        // map：接收Lambda，将元素转换成其他形式或提取信息，接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。
        List<String> list = Arrays.asList("aa", "bb", "cc");
        list.stream().map(String::toUpperCase).forEach(System.out::println);

        System.out.println("-------------------------------------");
        employees.stream().map(Employee::getName).forEach(System.out::println);

        System.out.println("-------------------------------------");
        Stream<Stream<Character>> streamStream = list.stream().map(TestStreamAPI2::filterCharacter);
        streamStream.forEach(s -> s.forEach(System.out::println));

        System.out.println("-------------------------------------");
        list.stream().flatMap(TestStreamAPI2::filterCharacter)
                .forEach(System.out::println);
    }

    private static Stream<Character> filterCharacter(String value) {
        List<Character> list = new ArrayList<>();
        for (char c : value.toCharArray()) {
            list.add(c);
        }

        return list.stream();
    }

    @Test
    public void test7() {
        // Stream的map和flatMap类似与Collection的add和addAll
        List<String> list = Arrays.asList("aa", "bb", "cc");

        List<Object> list1 = new ArrayList<>();
        list1.add(11);
        list1.add(22);
        list1.add(list);
        // [11, 22, [aa, bb, cc]]
        System.out.println(list1);

        List<Object> list2 = new ArrayList<>();
        list2.add(11);
        list2.add(22);
        list2.addAll(list);
        // [11, 22, aa, bb, cc]
        System.out.println(list2);
    }

    @Test
    public void test8() {
        // 排序
        // 	sorted：自然排序
        List<String> strings = Arrays.asList("ccc", "aaa", "ddd", "bbb", "fff", "eee");
        strings.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("-----------------------------------------");

        // 	sorted(Comparator com)：定制排序
        employees.stream().sorted((e1, e2) -> {
            if (e1.getAge() == e2.getAge()) {
                return e1.getName().compareTo(e2.getName());
            } else {
                return e1.getAge() - e2.getAge();
            }
        }).forEach(System.out::println);
    }

}
